package gui.dialog;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

import game.resources.*;
import main.Antiquity;

/**
 *	@(#)ResourceDialog.java
 *
 *	The <code>ResourceDialog</code> class is used to prompt after a player purchased a building
 *	and has more resources to pay with than the building costs. In this case it's the player's
 *	choice to choose which resources he wants to use for this purchase.
 *
 *	@author Grzegorz Kobiela
 *	@version 1.0 2008/4/20
 */
public final class ResourceDialog
extends JDialog
{
	/** The food observer. */
	private ResourceObservable obsFood;

	/** The luxury good observer. */
	private ResourceObservable obsLux;

	/**
	 *	Creates a new <code>ResourceDialog</code> instance demanding
	 *	the given player to pay the given amounts of resources.
	 *	@param owner the owner frame
	 *	@param player the player
	 *	@param food the amount of food to pay
	 *	@param lux the amount of luxury goods to pay
	 */
	public ResourceDialog(final gui.GameWindow owner, game.Player player, int food, int lux) {
		super(owner, String.format(Antiquity.get("dlgPaymentTitle"), player.getName()), true);
		obsFood = new ResourceObservable(food);
		obsLux = new ResourceObservable(lux);

		/* Dialog window */
		Container contentPane = getContentPane();
		contentPane.setLayout(null);
		contentPane.setBounds((Rectangle)Antiquity.getProperty("ResourceDialogInnerBounds"));

		/* Status bar */
		final JLabel status = new JLabel();
		status.setBounds((Rectangle)Antiquity.getProperty("ResourceDialogStatusBounds"));
		status.setText(getStatusText());
		contentPane.add(status);

		/* Resource box */
		Point padding = (Point)Antiquity.getProperty("ResourceDialogBoxPadding");
		final JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, padding.x, padding.y));
		panel.setBounds((Rectangle)Antiquity.getProperty("ResourceDialogBoxBounds"));
		panel.setBorder(BorderFactory.createLoweredBevelBorder());
		panel.setBackground(Antiquity.getColor("ResourceDialogBox"));
		contentPane.add(panel);

		/* Food to pay */
		if(food > 0) {
			final JPanel panelFish = createPanel(player, new Fish(), food);
			final JPanel panelGrain = createPanel(player, new Grain(), food);
			final JPanel panelOlives = createPanel(player, new Olives(), food);
			final JPanel panelSheep = createPanel(player, new Sheep(), food);
			if(panelFish != null) panel.add(panelFish);
			if(panelGrain != null) panel.add(panelGrain);
			if(panelOlives != null) panel.add(panelOlives);
			if(panelSheep != null) panel.add(panelSheep);
			obsFood.addObserver(
				new Observer() {
					public void update(Observable obs, Object obj) {
						status.setText(getStatusText());
						if(obsFood.getValue() == 0) {
							if(panelFish != null) panel.remove(panelFish);
							if(panelGrain != null) panel.remove(panelGrain);
							if(panelOlives != null) panel.remove(panelOlives);
							if(panelSheep != null) panel.remove(panelSheep);
							if(obsLux.getValue()> 0) {
								panel.invalidate();
								panel.repaint();
							} else {
								setVisible(false);
								dispose();
							}
						}
					}
				}
			);
		}

		/* Luxury goods to pay */
		if(lux > 0) {
			final JPanel panelDye = createPanel(player, new Dye(), lux);
			final JPanel panelGold = createPanel(player, new Gold(), lux);
			final JPanel panelPearls = createPanel(player, new Pearls(), lux);
			final JPanel panelWine = createPanel(player, new Wine(), lux);
			if(panelDye != null) panel.add(panelDye);
			if(panelGold != null) panel.add(panelGold);
			if(panelPearls != null) panel.add(panelPearls);
			if(panelWine != null) panel.add(panelWine);
			obsLux.addObserver(
				new Observer() {
					public void update(Observable obs, Object obj) {
						status.setText(getStatusText());
						if(obsLux.getValue() == 0) {
							if(panelDye != null) panel.remove(panelDye);
							if(panelGold != null) panel.remove(panelGold);
							if(panelPearls != null) panel.remove(panelPearls);
							if(panelWine != null) panel.remove(panelWine);
							if(obsFood.getValue() > 0) {
								panel.invalidate();
								panel.repaint();
							} else {
								setVisible(false);
								dispose();
							}
						}
					}
				}
			);
		}

		/* Dialog properties */
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		addWindowListener(
			new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					owner.showWarning(ResourceDialog.this, Antiquity.get("errNoClose"));
				}
			}
		);
		Rectangle bounds = (Rectangle)Antiquity.getProperty("ResourceDialogBounds");
		setLocation(
			owner.getX() + (owner.getWidth() - bounds.width) / 2,
			owner.getY() + (owner.getHeight() - bounds.height) / 2
		);
		setSize(bounds.getSize());
		setResizable(false);
		setVisible(true);
	}

	/**
	 *	Returns a panel displaying the given amount of resources
	 *	the given player has available for purchase.
	 *	@param player the player
	 *	@param resource the resource
	 *	@param n the amount to display
	 *	@return the panel
	 */
	private JPanel createPanel(final game.Player player, final Resource resource, int n) {
		n = Math.min(n, player.hasResource(resource.getClass()));
		if(n == 0) return null;
		final JPanel panel = new JPanel(null);
		panel.setPreferredSize(((Rectangle)Antiquity.getProperty("ResourceDialogPanelBounds")).getSize());
		panel.setOpaque(false);
		Point offset = (Point)Antiquity.getProperty("ResourceDialogPanelOffset");
		Point step = (Point)Antiquity.getProperty("ResourceDialogPanelStep");
		String tooltip = getToolTipText(resource, player.getResources(resource.getType()).size());
		for(int i = 0; i < n; i++) {
			ImageIcon icon = gui.GameUtilities.createIcon(resource);
			JButton button = new JButton(icon);
			button.setSize(icon.getIconWidth(), icon.getIconHeight());
			button.setLocation(offset.x + step.x * i, offset.y + step.y * i);
			button.setPreferredSize(button.getSize());
			button.setToolTipText(tooltip);
			button.addActionListener(
				new ActionListener() {
					public void actionPerformed(ActionEvent e) {
						Antiquity.pay(player, resource.getType());
						if(resource instanceof Food) {
							obsFood.decrease();
						} else {
							obsLux.decrease();
						}
						panel.remove(panel.getComponent(panel.getComponentCount() - 1));
						panel.invalidate();
						panel.repaint();
						String tooltip = getToolTipText(resource, player.getResources(resource.getType()).size());
						for(Component component: panel.getComponents()) ((JButton)component).setToolTipText(tooltip);
					}
				}
			);
			panel.add(button);
		}
		return panel;
	}

	/**
	 *	Returns the tooltip text for the given resource.
	 *	@param resource the resource
	 *	@param n the amount
	 */
	private String getToolTipText(Resource resource, int n) {
		return String.format(Antiquity.get("dlgResource"), n, Antiquity.get("res" + resource, n));
	}

	/**
	 *	Returns the text for the status bar.
	 *	@return the text
	 */
	private String getStatusText() {
		int food = obsFood.getValue();
		int lux = obsLux.getValue();
		String fd = (food > 0 ? gui.GameUtilities.getPrice(food, "Food") : "");
		String lx = (lux > 0 ? gui.GameUtilities.getPrice(lux, "Lux") : "");
		String and = ((!fd.equals("") && !lx.equals("")) ? String.format(" %s ", Antiquity.get("and")) : "");
		return String.format(Antiquity.get("dlgPaymentMessage"), fd + and + lx);
	}
}